package com.hd.trans.widgets;

import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.util.AttributeSet;
import android.util.Log;
import android.view.OrientationEventListener;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.hd.trans.utils.CamParaUtil;


/**
 * Created by gxj on 2018/2/17 01:46.
 * 相机预览封装
 */
public class CustomCameraPreview extends SurfaceView implements SurfaceHolder.Callback {

    private static String TAG = CustomCameraPreview.class.getName();

    private Camera mCamera;

    private boolean mTakingPicture;
    private boolean isAutoSize = true;//自动匹配最佳尺寸
    private boolean isHd = true;//高清以上画质
    private int ratioW = 0;
    private int ratioH = 0;

    public CustomCameraPreview(Context context) {
        super(context);
        init();
    }

    public CustomCameraPreview(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CustomCameraPreview(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public void setAutoSize(boolean isAutoSize){
        this.isAutoSize = isAutoSize;
    }
    public void isHd(boolean isHd){
        this.isHd = isHd;
    }

    private void init() {
        SurfaceHolder surfaceHolder = getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setKeepScreenOn(true);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    /**
     * 设置宽高比
     * @param width
     * @param height
     */
    public void setAspectRation(int width, int height){
        if (width < 0 || height < 0){
            throw new IllegalArgumentException("width or height can not be negative.");
        }

        Matrix matrix = calculateSurfaceHolderTransform(width, height);
        float[] values = new float[9];
        matrix.getValues(values);
        setTranslationX(values[Matrix.MTRANS_X]);
        setTranslationY(values[Matrix.MTRANS_Y]);
        setScaleX(values[Matrix.MSCALE_X]);
        setScaleY(values[Matrix.MSCALE_Y]);
        invalidate();
    }

    public Matrix calculateSurfaceHolderTransform(int cameraHeight, int cameraWidth) {
        Log.e("liaoyucheng", "cameraHeight = "+cameraHeight+", cameraWidth = "+cameraWidth);
        // 预览 View 的大小，比如 SurfaceView
        int viewHeight = getHeight();
        int viewWidth = getWidth();
        Log.e("liaoyucheng", "viewHeight = "+viewHeight+", viewWidth = "+viewWidth);
        // 相机选择的预览尺寸
//        int cameraHeight = configManager.getCameraResolution().x;
//        int cameraWidth = configManager.getCameraResolution().y;
        // 计算出将相机的尺寸 => View 的尺寸需要的缩放倍数
        float ratioPreview = ((float) cameraWidth) / ((float) cameraHeight);
        float ratioView = ((float) viewWidth) / ((float) viewHeight);
        float scaleX, scaleY;
        if (ratioView < ratioPreview) {
            scaleX = ratioPreview / ratioView;
            scaleY = 1;
        } else {
            scaleX = 1;
            scaleY = ratioView / ratioPreview;
        }
        // 计算出 View 的偏移量
        float scaledWidth = viewWidth * scaleX;
        float scaledHeight = viewHeight * scaleY;
        float dx = (scaledWidth - viewWidth) / 2;
        float dy = (scaledHeight - viewHeight) / 2;
        Log.e("liaoyucheng", "dx = "+dx+", dy = "+dy+", scaleX = "+scaleX+", scaleY = "+scaleY);

        Matrix matrix = new Matrix();
        matrix.postScale(scaleX, scaleY);
        matrix.postTranslate(0, 0);

        return matrix;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        if (0 == ratioW || 0 == ratioH){
            //未设定宽高比，使用预览窗口默认宽高
            setMeasuredDimension(width, height);
        }else {
            //设定宽高比，调整预览窗口大小（调整后窗口大小不超过默认值）
            if (width < height * ratioW / ratioH){
                setMeasuredDimension(width, width * ratioH / ratioW);
            }else {
                setMeasuredDimension(height * ratioW / ratioH, height);
            }
        }

    }

    public void surfaceCreated(SurfaceHolder holder) {
        Log.e("yang", "surfaceCreated 1");
        mCamera = CamParaUtil.openCamera();
        if (mCamera != null) {
            startPreview(holder);
            Log.e("yang", "surfaceCreated 2");
        }
    }

    public Camera getmCamera() {
        return mCamera;
    }

    /**
     * 重启相机
     */
    public void startPreview() {
        if (mCamera != null){
            mCamera.startPreview();
            mTakingPicture = false;
        }
    }

    /**
     * 停止相机
     */
    public void stopPreview() {
        if (mCamera != null){
            mCamera.stopPreview();
        }
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        Log.e("yang", "surfaceChanged 1");
        if (mCamera != null) {
            mCamera.stopPreview();
            startPreview(holder);
        }
        Log.e("yang", "surfaceChanged 2");
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        //回收释放资源
        release();
        Log.e("yang", "release");
    }

    /**
     * 预览相机
     */
    private void startPreview(SurfaceHolder holder) {
        try {
            mCamera.setPreviewDisplay(holder);
            Camera.Parameters parameters = mCamera.getParameters();
            if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                //竖屏拍照时，需要设置旋转90度，否者看到的相机预览方向和界面方向不相同
                mCamera.setDisplayOrientation(90);
                parameters.setRotation(90);
            } else {
                mCamera.setDisplayOrientation(0);
                parameters.setRotation(0);
            }
            parameters.setPictureFormat(PixelFormat.JPEG); // 设置图片格式
            parameters.setJpegQuality(100); // 设置照片质量
            Camera.Size bestSize;//获得相机支持的照片尺寸,选择合适的尺寸

            if(isAutoSize){
                bestSize = CamParaUtil.getBestSize(parameters.getSupportedPreviewSizes(),
                        getWidth(), getHeight(), isHd);
            }else {
                bestSize = CamParaUtil.getBestSize(parameters.getSupportedPreviewSizes());
            }
            if (bestSize != null) {
                Log.d("CustomCameraPreview", "width = "+bestSize.width+", height = "+bestSize.height);
                parameters.setPreviewSize(bestSize.width, bestSize.height);

                setAspectRation(bestSize.width, bestSize.height);
            } else {
                parameters.setPreviewSize(1920, 1080);
                parameters.setPictureSize(1920, 1080);
            }
            if (parameters.getSupportedFocusModes().contains(
                    Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);//用于拍照的连续自动对焦模式。
            }
            mCamera.setParameters(parameters);
            //mCamera.startPreview();
            getHandler().removeCallbacks(startPreviewRunnable);
            getHandler().postDelayed(startPreviewRunnable, 500);
//            focus();
        } catch (Exception e) {
            try {
                Camera.Parameters parameters = mCamera.getParameters();
                if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                    mCamera.setDisplayOrientation(90);
                    parameters.setRotation(90);
                } else {
                    mCamera.setDisplayOrientation(0);
                    parameters.setRotation(0);
                }
                parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);//用于拍照的连续自动对焦模式。
                mCamera.setParameters(parameters);
                mCamera.startPreview();
//                focus();
            } catch (Exception e1) {
                e.printStackTrace();
                mCamera = null;
            }
        }
    }

    private Runnable startPreviewRunnable = new Runnable() {
        @Override
        public void run() {
            if(mCamera != null){
                mCamera.startPreview();
            }
        }
    };

    /**
     * 释放资源
     */
    private void release() {
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }

    /**
     * 对焦，在CameraActivity中触摸对焦
     */
    public void focus() {
        if (mCamera != null) {
            mCamera.autoFocus(null);
        }
    }

    /**
     * 拍摄照片
     *
     * @param pictureCallback 在pictureCallback处理拍照回调
     */
    public void takePhoto(Camera.PictureCallback pictureCallback) {
        if (mCamera != null && !mTakingPicture) {
            mTakingPicture = true;
            //第一个参数--图像捕获回调，是一种最安全的回调方法， 它确保会被调用，并且在压缩图像时被调用。
            mCamera.takePicture(null, null, pictureCallback);
        }
    }

    public void resetTakingPicture() {
        mTakingPicture = false;
    }

    public class IOrientationEventListener extends OrientationEventListener {

        public IOrientationEventListener(Context context) {
            super(context);
        }

        @Override
        public void onOrientationChanged(int orientation) {
            if (ORIENTATION_UNKNOWN == orientation) {
                return;
            }
            Camera.CameraInfo info = new Camera.CameraInfo();
            Camera.getCameraInfo(1, info);
            orientation = (orientation + 45) / 90 * 90;
            int rotation = 0;
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                rotation = (info.orientation - orientation + 360) % 360;
            } else {
                rotation = (info.orientation + orientation) % 360;
            }
            Log.e("TAG", "orientation: " + orientation);
            if (null != mCamera) {
                Camera.Parameters parameters = mCamera.getParameters();
                parameters.setRotation(rotation);
                mCamera.setParameters(parameters);
            }
        }
    }

    public boolean isTakingPicture() {
        return mTakingPicture;
    }
}
